package com.woniuxy.aspect;

import com.woniuxy.annotation.PassLevelAnnotation;
import com.woniuxy.entity.dto.system.LoginDTO;
import com.woniuxy.entity.dto.system.LoginUserDTO;
import com.woniuxy.util.GetUserIdFromToken;
import com.woniuxy.util.JWTUtil;
import com.woniuxy.util.ResponseData;
import com.woniuxy.util.ResponseEnum;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.lang.reflect.Method;
import java.util.Arrays;

@Component
@Aspect
@EnableAspectJAutoProxy
public class LoggerAspect {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private final String PassStatus = "execution(* com.woniuxy.controller.UserController.login(..))";
    private final String LevelControl = "execution(* com.woniuxy.controller.LoginController.*(..)),(* com.woniuxy.controller.UserController.deptClean(..))";
    private final String increaseUser = "execution(* com.woniuxy.controller.ClientController.addClient(..))";

    @AfterReturning(pointcut = PassStatus, returning = "result")
    public void doAfter(JoinPoint joinPoint, ResponseData<?> result) {
        LoginDTO data = (LoginDTO) result.getData();
        Integer passLevel = data.getUserInfo().getPassLevel();
        // 存入redis，大key，小key是jwt，value是权限等级
        //在controller层的方法上，写自定义注解，在doBefore()内和自定义注解上的数字进行比较，来实现权限控制
        redisTemplate.opsForHash().put("CACHE:CHARGINGPLATFORM:AUTHORITYLEVEL", data.getJwt(), passLevel);
        System.out.println("权限等级是" + passLevel);
    }

    @Around(LevelControl)
    public ResponseData<?> doAround(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method aClass = signature.getMethod();

        if (aClass.isAnnotationPresent(PassLevelAnnotation.class)) {
            PassLevelAnnotation annotation = aClass.getAnnotation(PassLevelAnnotation.class);
            Integer userPassLevel = annotation.passLevel(); // 自定义注解在方法上写定一个权限等级的参数，得到了这个参数
            String token = GetUserIdFromToken.getTokenId();
            Integer systemPassLeveL = (Integer) redisTemplate.opsForHash().get("CACHE:CHARGINGPLATFORM:AUTHORITYLEVEL", token);
            try {
                if (systemPassLeveL >= userPassLevel) {
                    System.out.println("允许访问");
                    joinPoint.proceed();
                    return ResponseData.ok();
                } else {
                    return ResponseData.fail(ResponseEnum.PERMISSION_DENIED);
                }
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        return ResponseData.ok();
    }
    @Around("execution(* com.woniuxy.controller.UserController.deptClean(..))")
    public ResponseData<?> doAround1(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method aClass = signature.getMethod();

        if (aClass.isAnnotationPresent(PassLevelAnnotation.class)) {
            PassLevelAnnotation annotation = aClass.getAnnotation(PassLevelAnnotation.class);
            Integer userPassLevel = annotation.passLevel(); // 自定义注解在方法上写定一个权限等级的参数，得到了这个参数
            String token = GetUserIdFromToken.getTokenId();
            Integer systemPassLeveL = (Integer) redisTemplate.opsForHash().get("CACHE:CHARGINGPLATFORM:AUTHORITYLEVEL", token);
            try {
                if (systemPassLeveL >= userPassLevel) {
                    System.out.println("允许访问");
                    joinPoint.proceed();
                    return ResponseData.ok();
                } else {
                    return ResponseData.fail(ResponseEnum.PERMISSION_DENIED);
                }
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        return ResponseData.ok();
    }
}
